﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Ciripescu_WebRole.Entities;
using System.Data.Services.Client;
using Microsoft.Samples.ServiceHosting.StorageClient;

namespace Ciripescu_WebRole.BL
{
    public class VotManager
    {
        
        #region Public Methods

        public VotManager()
        {
            m_svcContext             = new MyServiceContext();
            m_svcContext.RetryPolicy = RetryPolicies.RetryN(3, TimeSpan.FromSeconds(1));
        }

        public IEnumerable<Vot> DoQuery(IQueryable<Vot> q)
        {
            TableStorageDataServiceQuery<Vot> query = new TableStorageDataServiceQuery<Vot>(q as DataServiceQuery<Vot>);
            IEnumerable<Vot> queryResults           = query.ExecuteAllWithRetries();
            return queryResults;
        }

        public Vot GetItem(string userName, string timeStamp)
        {
            try
            {
                return (DoQuery(from c in m_svcContext.Voturi where c.PartitionKey == userName && c.RowKey == timeStamp select c)).Single();
            }
            catch (Exception e)
            {
                Utils.WriteLog(EventLogName.Error, e.ToString());
                return null;
            }
        }

        /// <summary>
        /// Verifica daca exista un vot de la ip-ul dat in ultimele 24 de ore. Daca exista, il returneaza, in caz contrar returneaza null
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="IP"></param>
        /// <returns></returns>
        public Vot PoateVota(string userName, string IP)
        {
            Vot ultimulVot = null;
            try
            {
                ultimulVot = (from c in m_svcContext.Voturi where c.PartitionKey == userName && c.IP == IP select c).First<Vot>();
            }
            catch (Exception)
            {
                //daca intra aici inseamna ca ori a crapat azurul ori nu exista iregistrarea in baza de date.
                //destul de retardat nu?
            }
            if (ultimulVot != null)
            {
                TimeSpan ts = DateTime.Now.Subtract(ultimulVot.time);

                if (ts.TotalDays >= 1)
                    return null;
                else return ultimulVot;
            }
            else return null;
        }

        public void VoteazaUser(string userName, string IP, string userAgent)
        {
            Vot v = new Vot(userAgent, DateTime.Now, IP, userAgent);
            Insert(v);
            UserManager um = new UserManager();
            User u = um.GetItem(userName);
            u.Votes = CalcNbOfVotes(userName);
            um.Save(u);
        }
        public IEnumerable<Vot> GetAllItems()
        {
            var results = from c in m_svcContext.Voturi select c;
            return DoQuery(results);
        }

        public IEnumerable<Vot> GetVotesForUserName(string userName)
        {
            var results = from c in m_svcContext.Voturi where c.PartitionKey == userName select c;
            return DoQuery(results);
        }

        public void Delete(Vot itemToDelete)
        {
            m_svcContext.DeleteObject(itemToDelete);
            m_svcContext.SaveChanges();
        }

        public void DeleteWithoutQ(Vot itemToDelete)
        {
            m_svcContext.AttachTo(m_svcContext.UsersTableName, itemToDelete, "*");
            Delete(itemToDelete);
        }

        /// <summary>
        /// Updates an existing item from the tables.
        /// </summary>
        /// <param name="item"></param>
        public void Save(Vot item)
        {
            m_svcContext.UpdateObject(item);
            m_svcContext.SaveChanges();
        }

        /// <summary>
        /// Insert a new item in the tables.
        /// </summary>
        /// <param name="newItem"></param>
        public void Insert(Vot newItem)
        {
                m_svcContext.AddObject(m_svcContext.VoturiTableName, newItem);
                m_svcContext.SaveChanges();
        }
        

        /// <summary>
        /// Calculeaza nr de voturi primite de user
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="onUser"></param>
        /// <returns></returns>
        public int CalcNbOfVotes(string user)
        {
            var votes = GetVotesForUserName(user);
            return votes.ToList<Vot>().Count;
        }
        
        #endregion

        #region Private Methods


        #endregion 

        #region Private Members

        private MyServiceContext m_svcContext = null;
        
        #endregion
    }
}
